#include<stdio.h>
#include<stdbool.h>

#include<graphics.h>     //第三方图形库

//用于导入音频头文件
#include<mmsystem.h>
#pragma comment(lib,"winmm.lib") 

#include<conio.h>
#include<time.h>
#include<math.h>

#define WIDTH 1024              //窗口大小
#define HEIGHT 640

#define MAP_WIDTH (WIDTH*3)     //地图大小
#define MAP_HEIGHT (HEIGHT*3)

#define FOOD_NUM 1000     //食物数量

//玩家 食物 AI     -> 属性：坐标（x ，y） 颜色     球：radius（半径） ，flag（食物）

//球的结构
struct Ball        
{
	int x;
	int y;
	int r;         //球的半径
	bool flag;     //是否存货 true / false
	DWORD color;   //颜色
};

struct Ball player;     //玩家

struct Ball food[FOOD_NUM];

//地图 图片
IMAGE map(MAP_WIDTH, MAP_HEIGHT);

//摄像机坐标
POINT g_cameraPos;     //一种结构体

void createFood(int i)
{
	//通过取模使得食物坐标不超出地图，半径不大于玩家初始半径 且 不为0
	food[i].x = rand() % MAP_WIDTH;
	food[i].y = rand() % MAP_HEIGHT;
	food[i].r = rand() % 5 + 1;

	food[i].flag = true;

	food[i].color = RGB(rand() % 256, rand() % 256, rand() % 256);     //使用RGB三原色合成一个颜色
}

void gameInit()
{
	//向多媒体设备接口发送字符串函数
	mciSendString(TEXT("open music.mp3 alias BGM"), 0, 0, 0);
	mciSendString(TEXT("play BGM"),0,0,0);

	//随机数种子
	srand((unsigned)time(NULL));

	//初始化玩家
	player.x = rand() % MAP_WIDTH;
	player.y = rand() % MAP_HEIGHT;
	player.r = 10;
	player.flag = true;

	//初始化食物
	for (int i = 0; i < FOOD_NUM; i++)
	{
		createFood(i);
	}
}

void gameDraw()
{
	//设置绘制的图片  窗口也是一张图片
	SetWorkingImage(&map);

	//设置背景颜色
	setbkcolor(WHITE);

	cleardevice();            //cleardevice:清除设备函数->可用于图形窗口
							  
	//画格子
	setlinecolor(RGB(230, 231, 239));
	for (int i = 0; i < MAP_WIDTH; i += 10)
	{
		line(i, 0, i, MAP_HEIGHT);     //竖线
		line(0, i, MAP_WIDTH, i);      //横线
	}

	//绘制食物
	for (int i = 0; i < FOOD_NUM; i++)
	{
		if (!food[i].flag)     //跳过不存在的食物
			continue;
		setfillcolor(food[i].color);
		solidcircle(food[i].x, food[i].y, food[i].r);
	}

	//绘制玩家


		//画圆 到 图形窗口
	setfillcolor(RED);                           //填充实心圆为红色
	solidcircle(player.x, player.y, player.r);     //画一个实心圆

	SetWorkingImage();

	//把地图输出到屏幕上
	putimage(0, 0, WIDTH, HEIGHT, &map, g_cameraPos.x, g_cameraPos.y);

	{
		//以玩家为中心，计算摄像机的坐标（实际是将玩家视角左上角坐标当成摄像机坐标）
		g_cameraPos.x = player.x - WIDTH / 2;
		g_cameraPos.y = player.y - HEIGHT / 2;

		//防止摄像机越界
		if (g_cameraPos.x < 0) g_cameraPos.x = 0;
		if (g_cameraPos.y < 0) g_cameraPos.y = 0;
		if (g_cameraPos. x > MAP_WIDTH - WIDTH) g_cameraPos.x = MAP_WIDTH - WIDTH;
		if (g_cameraPos.y > MAP_HEIGHT - HEIGHT) g_cameraPos.y = MAP_WIDTH - HEIGHT;
	}
}

//控制玩家移动
void movePlayer(int speed)
{

/*
	//手动控制玩家球移动
	//获取键盘按键信息，getchar , scanf , gets 都不合适，它们输入数据后需要按下回车
	//_getch 按下即可触发，不需要回车，需要包含头文件 conio.h
	char key = _getch();
	//printf("%d_%c\n", key, key);      //上键：72； 下键：80； 左键：75； 右键：77；

	switch (key)
	{
		case 72:          //上
			player.y -= 2;
			break;
		case 80:          //下
			player.y += 2;
			break;
		case 75:          //左
			player.x -= 2;
			break;
		case 77:          //右
			player.x += 2;
			break;
		case 'w':		  //上
			player.y -= 2;
			break;
		case 's':         //下
			player.y += 2;
			break;
		case 'a':         //左
			player.x -= 2;
			break;
		case 'd':         //右
			player.x += 2;
			break;
		case 'W':         //上
			player.y -= 2;
			break;
		case 'S':         //下
			player.y += 2;
			break;
		case 'A':         //左
			player.x -= 2;
			break;
		case 'D':         //右
			player.x += 2;
			break;

	}
*/

//由于 _getch 函数不可实现 左上，右上 这些位移，故接下来使用 GetAsyncKeyState 改进

#if 0
#else
	//getasynckeystate获取异步按键状态，这个函数比_getch()更流畅，而且可以同时按键
	if (GetAsyncKeyState(VK_UP))     //VK ： virtual key 虚拟键值
	{
		if (player.r <= 10)
		{
			player.y -= speed;
		}
		else if (player.r <= 20)
		{
			player.y -= speed - 5;
		}
		else
		{
			player.y -= speed - 7;
		}
	}

	if (GetAsyncKeyState(VK_DOWN))
	{
		if (player.r <= 10)
		{
			player.y += speed;
		}
		else if (player.r <= 20)
		{
			player.y += speed - 5;
		}
		else
		{
			player.y += speed - 7;
		}
	}

	if (GetAsyncKeyState(VK_LEFT))
	{
		if (player.r <= 10)
		{
			player.x -= speed;
		}
		else if (player.r <= 20)
		{
			player.x -= speed - 5;
		}
		else
		{
			player.x -= speed - 7;
		}
	}

	if (GetAsyncKeyState(VK_RIGHT))
	{
		if (player.r <= 10)
		{
			player.x += speed;
		}
		else if (player.r <= 20)
		{
			player.x += speed - 5;
		}
		else
		{
			player.x += speed - 7;
		}
	}

	
#endif
}

//玩家 和 食物 之间的圆心距
double distance(struct Ball *b1, struct Ball *b2)
{
	return sqrt((b1->x - b2->x) * (b1->x - b2->x) + (b1->y - b2->y) * (b1->y - b2->y));
}

void PlayerEatFood()
{
	for (int i = 0; i < FOOD_NUM; i++)
	{
		if (food[i].flag && distance(&food[i],&player) < player.r)
		{
			food[i].flag = false;
			player.r += food[i].r / 2;

			//食物重新生成
			createFood(i);
		}
	}
}

/*
ai:和玩家类似，主要是如何移动（让ai来追玩家 吃食物 相互吃）
 初始化 绘制 ...

*/


void ball_decreace()     //球随时间自动变小
{	
	static int n = 0;

	if (n >= 20&&player.r>5) {
		player.r--;
		n = 0;
	}
	n++;
}

int main()
{
	initgraph(WIDTH,  HEIGHT,  EW_SHOWCONSOLE-1);  //黑窗口 -> 图形窗口
	//EW_SHOWCONSOLE 显示控制台窗口                                         

	gameInit();

	printf("%d %d %d %d", player.x, player.y, player.r, player.flag);

	system("cls");               //system("cls"):清屏函数->用于控制台窗口

	BeginBatchDraw();     //开始缓冲

	while (1)
	{
		gameDraw();
		movePlayer(10);

		PlayerEatFood();

		FlushBatchDraw();     //刷新

		ball_decreace();

		Sleep(50);
	}

	closegraph();

	return 0;
}
